// ViewHex.cpp : implementation file
//

#include "stdafx.h"
#include "LogViewer.h"
#include "ViewHex.h"


#define COLOR_HEX_BKGND RGB(240, 240, 255)

IMPLEMENT_DYNAMIC(CViewHex, CDialog)

CViewHex::CViewHex(CWnd* pParent /*=NULL*/)
	: CDialog(CViewHex::IDD, pParent)
{
	m_br.CreateSolidBrush(COLOR_HEX_BKGND);
	m_data = 0;
}

CViewHex::~CViewHex()
{
	delete [] m_data;
}

void CViewHex::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDHEX, m_edit);
}


BEGIN_MESSAGE_MAP(CViewHex, CDialog)
	ON_WM_CTLCOLOR()
	ON_BN_CLICKED(IDC_SAVEAS, &CViewHex::OnBnClickedSaveas)
END_MESSAGE_MAP()

CString CViewHex::FmtHex(PBYTE data, DWORD datalen)
{
	CString str;
	TCHAR buf[100];
	TCHAR * tbl = L"0123456789abcdef";
	int addr = 0;
	for (;datalen; data=data+16, addr=addr+16, datalen = datalen - min(datalen, 16))
	{
		TCHAR * p = buf;
		*p++ = tbl[(addr >> 20) & 0xf];
		*p++ = tbl[(addr >> 16) & 0xf];
		*p++ = tbl[(addr >> 12) & 0xf];
		*p++ = tbl[(addr >>  8) & 0xf];
		*p++ = tbl[(addr >>  4) & 0xf];
		*p++ = tbl[(addr >>  0) & 0xf];
		*p++ = ' ';
		*p++ = ' ';
		p[48] = ' ';
		p[49] = ' ';
		for (DWORD i=0; i<16; ++i)
		{
			if (i < datalen)
			{
				p[i*3+0] = tbl[data[i] >>  4];
				p[i*3+1] = tbl[data[i] & 0xf];
				p[i*3+2] = (i == 7) ? '-' : ' ';
				p[50+i] = (data[i]>0x20 && data[i]<0x7f) ? data[i] : '.';
			}
			else
			{
				p[i*3+0] = ' ';
				p[i*3+1] = ' ';
				p[i*3+2] = ' ';
				p[50+i] = ' ';
			}
		}
		p += 50 + 16;
		*p++ = '\r';
		*p++ = '\n';
		*p++ = 0;
		str += buf;
	}
	return str;
}

BOOL CViewHex::OnInitDialog()
{
	CDialog::OnInitDialog();

	CString str = FmtHex(m_data, m_datalen);
	m_edit.SetWindowText(str);

	return TRUE;  // return TRUE unless you set the focus to a control
	// EXCEPTION: OCX Property Pages should return FALSE
}

HBRUSH CViewHex::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	HWND hEd = ::GetDlgItem(m_hWnd, IDC_EDHEX);
	if (hEd == pWnd->GetSafeHwnd())
	{
		pDC->SetBkColor(COLOR_HEX_BKGND);
		pDC->SetTextColor(0);
		return m_br;
	}
	else
	{
		HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
		return hbr;
	}
}

void CViewHex::OnBnClickedSaveas()
{
	CFileDialog fd(FALSE, NULL, NULL, OFN_OVERWRITEPROMPT, L"all files(*.*)|*.*||");
	fd.m_ofn.Flags |= OFN_NOCHANGEDIR;
	ASSERT(fd.m_ofn.Flags & OFN_EXPLORER);
	if (fd.DoModal() == IDOK)
	{
		CString strFile = (LPCWSTR)fd.GetPathName();
		CFile file;
		file.Open(strFile, CFile::modeCreate|CFile::modeWrite);
		file.Write(m_data, m_datalen);
	}
}
